#include "interface/chat/Lexer.hh"
#include "interface/chat/Token.hh"

#include "stl.h"


// default Ctor
Lexer::Lexer(std::string input)
  : _input(input),
    _len (_input.length()),
    _nbSeparator (STRLEN_CHAT_SEPARATOR_STRING)
{
  buildTokenList();
}


std::vector<e_token> Lexer::buildTokenList()
{
  int i = 0;
  unsigned int inputIndex = 0;
  std::string currentString; // building string

  // for each char found, add it to current string
  // try to identify currentString as a know token
  for (; inputIndex < _len; ++inputIndex)
  {
    currentString += _input[inputIndex];

    e_token tok;
    if ((tok = matchToken(currentString)) != TOK_UNKNOWN)
    {
      _tokenList[i++] = tok;
      currentString = "";
      continue;
    }

    // add quotting here
    if (_input[inputIndex] == TOK_SEPARATOR)
    {
      // we reached end of token and we didn't recognize it
      _tokenList[i++] = TOK_UNKNOWN; //TOK_IDENTIFIER, numeric;
      currentString = "";
    }
  }

  _tokenList[i] = TOK_EOT; // End of Transmission

  return _tokenList;
}


e_token Lexer::matchToken(std::string str)
{
  // NOTE: insert quotting managment here (&& NON_CURRENT_QUOTTING)
  // reaching token end
//  while (currentChar != CHAT_TOKEN_SEPARATORS && prevChar != CHAT_ESCAPE_CHAR)

  if (str.length() == 1)
    return (matchOneCharToken(str[0]));

  // ssize_t tmp = 0;
  // char buf[CHAT_MAX_ENTRY_LENGTH];
  // int count = CHAT_MAX_ENTRY_LENGTH;

  // while (tmp = read(_fd, buf, count) && tmp != '\0' && tmp != ' ')
  //   tok += tmp;

  // #ifdef DEBUG
  // std::cout << "tok: " << tok << std::endl;
  // #endif

  return TOK_UNKNOWN;
}


e_token Lexer::matchOneCharToken(char c)
{
  // browsing all tokens, trying to match the right one

  if (isSeparator(c))
    return TOK_SEPARATOR;

  switch (c)
  {
    case TOK_PIPE:
    case TOK_LPARENT:
    case TOK_RPARENT:
    case TOK_STAR:
    case TOK_PLUS:
    case TOK_DASH:
    case TOK_CMD:
    case TOK_QUOTE:
    case TOK_ESCAPE:
    case TOK_VALUE:
    case TOK_OPERATOR:
    case TOK_EOT:
    case TOK_SPACE:
    case TOK_EOL:
      return (e_token) c; // TODO: check this
  }

  return TOK_UNKNOWN;
}



char Lexer::isSeparator(char c)
{
  // browse CHAT_SEPARATOR_STRING, trying to match a separator char
  for (unsigned int i(0); i < _nbSeparator; ++i)
  {
    if (c == CHAT_SEPARATOR_STRING[i])
      return c;
  }

  // c wasn't a separator
  return '\0';
}
